《Android 基础(七)》 DrawerLayout and NavigationView

介绍

DrawerLayout是Support Library包中实现了侧滑菜单效果的控件
android.support.v4.widget.DrawerLayout
NavigationView是一个导航菜单框架,使用menu资源填充数据
常用来配合DrawerLayout使用

基本使用

DrawerLayout

布局文件

1
2
3
4
5
6
7
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/drawerlayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
……
</android.support.v4.widget.DrawerLayout>

使用DrawerLayout的时候需要将该布局作为根布局,然后在DrawerLayout中添加其他布局作为显示界面。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
drawerLayout = (DrawerLayout) findViewById(R.id.drawerlayout);获取DrawerLayout对象

//设置监听事件,监听DrawerLayout的状态,打开,关闭,滑动距离,状态改变,可以实现自己的定制
drawerLayout.addDrawerListener(new DrawerLayout.DrawerListener() {
@Override
public void onDrawerSlide(View drawerView, float slideOffset) {
Log.e(TAG , " onDrawerSlide slideOffset = " + slideOffset);
}

@Override
public void onDrawerOpened(View drawerView) {
Log.e(TAG , " onDrawerOpened ");
}

@Override
public void onDrawerClosed(View drawerView) {
Log.e(TAG , " onDrawerClosed ");
}

@Override
public void onDrawerStateChanged(int newState) {
Log.e(TAG , " onDrawerStateChanged ");
}
});

DrawerLayout的状态监听,listener的回调提供给开发者使用。

布局文件

header.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="240dp"
android:background="@color/colorPrimaryDark"
android:orientation="vertical">

//引用GitHub上的开源库
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/civ_profile"
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_alignParentLeft="true"
android:layout_marginLeft="24dp"
android:layout_marginStart="24dp"
android:layout_marginTop="20dp"
android:src="@drawable/logo" />

<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/civ_profile"
android:layout_below="@+id/civ_profile"
android:layout_marginTop="10dp"
android:text="Askmak Sharon"
android:textColor="#FFFFFF"
android:textSize="8pt"
android:textStyle="bold" />

<TextView
android:id="@+id/tv_email"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/civ_profile"
android:layout_below="@+id/tv_name"
android:layout_marginTop="10dp"
android:text="onlyloveyd@gmail.com"
android:textColor="#FFFFFF"
android:textSize="8pt"
android:textStyle="italic" />
</RelativeLayout>

这里使用了Github上的开关库de.hdodenhof.circleimageview.CircleImageView,其中可以设置一些属性,这里没有设置,可能是因为我使用的图片风格的原因,将头像的边框加上去后看上去不是那么协调

属性 意义
app:civ_border_color=”” 边框颜色
app:civ_border_width=”” 边框宽度
app:civ_fill_color=”” 填充颜色

second_menu.xml
这里只是名字叫做second_menu而已,没有其他的意思,只是一个普通的menu资源文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

<item
android:id="@+id/nv_profile"
android:icon="@drawable/profile"
android:orderInCategory="80"
android:title="Profile" />

<item
android:id="@+id/nv_video"
android:icon="@drawable/video"
android:orderInCategory="90"
android:title="Video" />

<item
android:id="@+id/nv_help"
android:icon="@drawable/help"
android:orderInCategory="100"
android:title="Help" />
</menu>

这个menu资源是用来在NavigationView中使用的导航菜单

activity_main.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/drawerlayout"
android:layout_width="match_parent"
android:layout_height="match_parent">


<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">

<include layout="@layout/toolbar"></include>

<FrameLayout
android:id="@+id/frame"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/content_iv"
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@mipmap/ic_launcher"/>
</FrameLayout>

</LinearLayout>

<android.support.design.widget.NavigationView
android:id="@+id/nv_left"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="@layout/header"
app:menu="@menu/second_menu">
</android.support.design.widget.NavigationView>

</android.support.v4.widget.DrawerLayout>

比较关键的几个点
android:layout_gravity=“start”
app:headerLayout=”@layout/header”//头布局
app:menu=”@menu/second_menu”//菜单资源

代码

MainActivity.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package mraz.com.actionbardemo;

import android.os.Bundle;
import android.support.design.widget.NavigationView;
import android.support.design.widget.Snackbar;
import android.support.v4.view.MenuItemCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.SearchView;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;

public class MainActivity extends AppCompatActivity {

public static String TAG = "yidong";
DrawerLayout drawerLayout;
NavigationView navigationView;
Toolbar toolbar;
ImageView imageView;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

drawerLayout = (DrawerLayout) findViewById(R.id.drawerlayout);
toolbar = (Toolbar) findViewById(R.id.toolbar);
navigationView = (NavigationView) findViewById(R.id.nv_left);
imageView = (ImageView) findViewById(R.id.content_iv);

setSupportActionBar(toolbar);
toolbar.setNavigationIcon(R.drawable.ic_menu_black_24dp);

drawerLayout.addDrawerListener(new DrawerLayout.DrawerListener() {
@Override
public void onDrawerSlide(View drawerView, float slideOffset) {
Log.e(TAG , " onDrawerSlide slideOffset = " + slideOffset);
}

@Override
public void onDrawerOpened(View drawerView) {
Log.e(TAG , " onDrawerOpened ");
}

@Override
public void onDrawerClosed(View drawerView) {
Log.e(TAG , " onDrawerClosed ");
}

@Override
public void onDrawerStateChanged(int newState) {
Log.e(TAG , " onDrawerStateChanged ");
}
});

navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(MenuItem item) {
if(drawerLayout.isDrawerOpen(Gravity.LEFT))
drawerLayout.closeDrawer(Gravity.LEFT);

switch(item.getItemId()) {
case R.id.nv_profile:
imageView.setImageResource(R.drawable.profile);
break;
case R.id.nv_video:
imageView.setImageResource(R.drawable.video);
break;
case R.id.nv_help:
imageView.setImageResource(R.drawable.help);
break;
}

return true;
}
});
}
……

}

针对NavigationView中的Menu设置响应事件,使用的方式和上一篇中ActionBar中的菜单资源使用方式相似,都是用过getItemId获取资源的id,然后以此作为依据进行对应的响应操作

ActionBar和DrawerLayout配合

一般用户的操作就是右滑或者点击ActionBar左上角的Icon出现左侧抽屉菜单
左侧滑动上面的内容已经实现了,点击ActionBar实现抽屉菜单的开关只需要针对左上角的ActionBar的图标做对应的事件处理即可。

1
2
setSupportActionBar(toolbar);
toolbar.setNavigationIcon(R.drawable.ic_menu_black_24dp);

然后在onOptionsItemSelected中

1
2
3
4
5
case android.R.id.home:
if(!drawerLayout.isDrawerOpen(Gravity.LEFT)) {
drawerLayout.openDrawer(Gravity.LEFT, true);
}
break;

因为ActionBar的NavigationIcon对应的资源ID就是
android.R.id.home
根据这个资源ID定制对应的事件响应,上面就是简单的打开左侧的抽屉菜单

效果图

这里写图片描述

ActionBar左上角图标响应

这里写图片描述

####源代码
###点击下载源代码###

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×